A computer system may include one or more parts, such as processors, peripheral devices, device controllers, and memories, which are utilizable by other devices of the system as resources for the execution of system tasks. For example, a processor may utilize a memory section as a resource for storage of results or as a source of data and instructions; that processor may also utilize an input/output device as a resource for communicating with the outside world. Or a direct memory access (DMA) controller may utilize a memory as a resource for storing data and a peripheral device as a resource for providing data, while an I/O device may utilize a device controller as a resource for communicating with a processor or a memory.
Simultaneous use by a plurality of devices of the same resource is likely to produce errors. For example, incorrect data will be obtained from memory, or the output of a printer will be garbled. It is therefore important that such systems have means for providing an indication to devices interested in using a resource of whether that resource is free and available for use as a resource, or whether it is presently busy, acting as a resource for some device of the system and therefore unavailable to act as a resource for other devices. It is also desirable to provide therewith means of preventing a device wishing to access and utilize a busy resource from doing so until the resource becomes freed by its owner, that is, its current user.
Prior approaches to meeting these requirements have traditionally involved the use of software locks. A software lock is a program-implemented scheme of providing a user with exclusive access to a shared resource. Such software locks have commonly taken the form of semaphores, which are flags, such as register or memory word contents or flip/flop states, that indicate the busy/free states of an associated resource. Semaphore program routines test the status of the flag, generally through a test-and-set type of instruction, and prevent a device desirous of becoming a resource user from accessing the desired resource while its associated flag indicates that it is being utilized by some other user.
The prior art locking mechanisms suffer from a number of disadvantages that generally flow from their software nature. The locks commonly require a program which tests the busy/free status of the resource and either locks the free resource for use by the new user and unlocks the resource when the user no longer desires it, or makes a decision as to what to do next and then directs the device to the selected activity when the resource is busy. The program may be of substantial length, and thus may occupy a significant portion of memory, particularly when numerous locks are used and the program must be replicated for each lock.
Avoidance of replication of the lock program by incorporating it into a subroutine may alleviate the above problem, but in turn creates a new one. The subroutine calls and returns and associated trap-induced context switches during program execution take time and tie up resources, such as processors and memory, and thus adversely affect system efficiency.
If the desired resource is found to be busy, the device wishing to use the resource must periodically recheck the status of the resource to determine when the resource becomes free. This not only requires additional program text to direct the device to recheck the resource status, but also ties up other resources, such as the bus between the device and the resource, which are utilized in performing the status check.
While an interrupt may be utilized to inform the devices that a resource is free, and thus rechecking by the devices of the resource status may be avoided, interrupt-based schemes have the disadvantage that they interrupt not only all of the devices wishing to use the resource, but all other devices as well. This adversely affects system efficiency. Masking of the interrupts at devices not desiring access to the resource is not a satisfactory solution because of the software complexity which masking requires.
Furthermore, informing all of a plurality of devices desirous of accessing a formerly busy resource that it has become free creates a free-for-all race to capture the resource, which requires a repetition of the above-described activities, along with their attendant disadvantages.
There is the further possibility that in such a free-for-all, one or more devices will become locked out and will seldom or never obtain access to the resource. Neither the interrupt scheme nor the status check loop scheme provide a wholly satisfactory solution to this problem. In the above-described interrupt scheme, for example, provision of a means for selecting a device and selectively masking the interrupt to all but the selected device adds further software and complexity to the scheme.
Similarly, in the above-described status check loop scheme which forces devices to perform a program loop to periodically recheck the status of a busy resource, the provision of an arbitration scheme to select one from a plurality of devices wishing to access the shared resource requires additional software and consumes time and system resources in executing the arbitration program's instructions.
In addition to the disadvantages enumerated above, the prior art locking schemes have generally not proved wholly effective in preventing access to locked, i.e. busy, shared resources. When implemented at the level of the executing program, locks have been accessible to programmers, and therefore it has been necessary to rely on cooperation from the programmers in observing the locks, by incorporating the locks into their programs, or at least in not willfully avoiding the locks. Thus, it has been simple for programmers to bypass the locks, often simply by ignoring them. Conversely, when implemented at the level of the operating system to avoid having to rely on use by the programmers, the locks could not efficiently be associated with every attempted access to a resource like shared memory, because of the severe overhead and resulting deterioration in system performance that lock-associated traps, or interrupts, produce.
Lastly, as was mentioned above, software locks are generally constructed around the use of a test and set type of instruction. But many program controlled systems do not have this type of instruction, and therefore retrofitting of lock capability into such systems has generally been very difficult.